package ua.com.alus.resvac.crm.services.spring;

import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import ua.com.alus.resvac.crm.domen.dao.AccountDao;
import ua.com.alus.resvac.crm.domen.dao.PhotoDao;
import ua.com.alus.resvac.crm.domen.dao.ResumeAccountDetailsDao;
import ua.com.alus.resvac.crm.domen.dao.VacancyAccountDetailsDao;
import ua.com.alus.resvac.crm.domen.entities.Account;
import ua.com.alus.resvac.crm.domen.entities.ResumeAccountDetails;
import ua.com.alus.resvac.crm.domen.entities.VacancyAccountDetails;

import javax.persistence.NoResultException;

/**
 * Implementation of AccountService
 * <p/>
 * Created by Usatov Alexey
 */
public class AccountServiceImpl implements AccountService {

    private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();

    public AuthenticationTrustResolver getAuthenticationTrustResolver() {
        return authenticationTrustResolver;
    }

    private AccountDao accountDao;

    private ResumeAccountDetailsDao resumeAccountDetailsDao;

    private VacancyAccountDetailsDao vacancyAccountDetailsDao;


    public AccountDao getAccountDao() {
        return accountDao;
    }

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    public ResumeAccountDetailsDao getResumeAccountDetailsDao() {
        return resumeAccountDetailsDao;
    }

    public void setResumeAccountDetailsDao(ResumeAccountDetailsDao resumeAccountDetailsDao) {
        this.resumeAccountDetailsDao = resumeAccountDetailsDao;
    }

    public VacancyAccountDetailsDao getVacancyAccountDetailsDao() {
        return vacancyAccountDetailsDao;
    }

    public void setVacancyAccountDetailsDao(VacancyAccountDetailsDao vacancyAccountDetailsDao) {
        this.vacancyAccountDetailsDao = vacancyAccountDetailsDao;
    }

    private PhotoDao photoDao;

    public PhotoDao getPhotoDao() {
        return photoDao;
    }

    public void setPhotoDao(PhotoDao photoDao) {
        this.photoDao = photoDao;
    }

    public String getUserName() {
        Authentication authentication;
        if ((authentication = SecurityContextHolder.getContext().getAuthentication()) != null) {
            if (getAuthenticationTrustResolver().isAnonymous(authentication)) {
                return null;
            }
            return ((User) authentication.getPrincipal()).getUsername();
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveResumeAccount(Account account, ResumeAccountDetails resumeAccountDetails) {
        getAccountDao().merge(account);
        getResumeAccountDetailsDao().merge(resumeAccountDetails);
    }

    @Transactional(readOnly = true)
    public Account getAccount(String username) {
        if (username == null) {
            return null;
        }
        try {
            return (Account) accountDao.getEntityManager().
                    createNamedQuery(Account.SELECT_BY_USERNAME).setParameter("userName", username).getSingleResult();
        } catch (NoResultException nre) {
            return null;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void removePhoto(String uuid) {
        getPhotoDao().remove(getPhotoDao().findById(uuid));
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void removeAccount(String uuid) {
        getAccountDao().remove(getAccountDao().findById(uuid));
    }

    @Override
    @Transactional(readOnly = true)
    public ResumeAccountDetails getResumeAccountDetails(String accountUuid) {
        return (ResumeAccountDetails) getResumeAccountDetailsDao().getEntityManager().
                createNamedQuery(ResumeAccountDetails.GET_RESUME_ACCOUNT_DETAILS).
                setParameter("accountUuid", accountUuid).getSingleResult();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveVacancyAccount(Account account, VacancyAccountDetails vacancyAccountDetails) {
        getAccountDao().merge(account);
        getVacancyAccountDetailsDao().merge(vacancyAccountDetails);
    }

    @Override
    @Transactional(readOnly = true)
    public VacancyAccountDetails getVacancyAccountDetails(String accountUuid) {
        return (VacancyAccountDetails) getVacancyAccountDetailsDao().getEntityManager().
                createNamedQuery(VacancyAccountDetails.GET_VACANCY_ACCOUNT_DETAILS).
                setParameter("accountUuid", accountUuid).getSingleResult();
    }
}
